package com.ilikesoup.instant.split;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.RecursiveAction;
import java.util.function.Consumer;

public class BatchSplitRunner<T> {

    private SplitExecutor<T> splitExecutor;

    public void batchConsume(Consumer<List<T>> consumer) {
        ListSupplier<T> supplier = splitExecutor.getSupplier();
        ListSplitter<T> splitter = splitExecutor.getSplitter();
        while(supplier.hasNext()) {
            List<List<T>> splitLists = splitter.apply(supplier.next());
            splitLists.forEach(consumer);
        }
    }

    public void consume(Consumer<T> consumer) {
        ListSupplier<T> supplier = splitExecutor.getSupplier();
        ListSplitter<T> splitter = splitExecutor.getSplitter();
        while(supplier.hasNext()) {
            List<List<T>> splitLists = splitter.apply(supplier.next());
            splitLists.forEach(o -> o.forEach(consumer));
        }
    }

    public void consumeParallel(Consumer<List<T>> consumer) {
        ListSupplier<T> supplier = splitExecutor.getSupplier();
        ListSplitter<T> splitter = splitExecutor.getSplitter();
        List<Runnable> runnableList;
        while(supplier.hasNext()) {
            List<List<T>> splitLists = splitter.apply(supplier.next());
            splitLists.forEach(subList -> CompletableFuture.runAsync(() -> consumer.accept(subList)));
        }
    }

    public static abstract class BatchSplitAction<T> extends RecursiveAction {
        /**
         * 待处理列表
         */
        protected final List<T> list;
        protected final Consumer<List<T>> listConsumer;

        public BatchSplitAction(List<T> list, Consumer<List<T>> listConsumer) {
            this.list = list;
            this.listConsumer = listConsumer;
        }

        @Override
        protected void compute() {

        }

        /**
         * 实际执行计算的方法
         *
         * @return
         */
        protected abstract void doCompute();

        /**
         * 创建子任务的方法，根据具体实现创建子任务
         *
         * @param subList
         * @param batchSize
         * @return
         */
        protected abstract RecursiveAction createSubTask(List<T> subList, int batchSize);
    }

}
